import { random } from '../functions/utils';
type Type = 'number' | 'string';
export class LuckyInfo {
  constructor(
    public title: string,
    public count: number,
    public showCount: number,
    public showModel: string[],
    public showedCount: number,
    public showedModel: string[]
  ) {}
}
export interface LuckyDog {
  id: string;
  title: string;
  type: Type;
  number?: number;
  string?: string[];
}
export abstract class AbstractLuckyDog implements LuckyDog {
  public count: number;
  protected showModel: string[] = [];
  protected showedModel: string[] = [];
  constructor(public id: string, public title: string, public type: Type) {}
  info(): LuckyInfo {
    return new LuckyInfo(
      this.title,
      this.count,
      this.showModel.length,
      this.showModel,
      this.showedModel.length,
      this.showedModel
    );
  }
  show() {
    return this.showModel[random(0, this.showModel.length - 1)];
  }
  random(): string {
    const result = random(0, this.showModel.length - 1);
    const showed = this.showModel.splice(result, 1)[0];
    this.showedModel.push(showed);
    return showed;
  }
  reset() {
    this.showModel.length = 0;
    this.showedModel.length = 0;
    this.init();
  }
  protected abstract init();
}
export class NumberLuckyDog extends AbstractLuckyDog {
  constructor(id: string, title: string, type: Type, public number: number) {
    super(id, title, type);
    this.count = number;
    this.init();
  }
  protected init() {
    for (let i = 1, len = this.count; i <= len; i++) {
      this.showModel.push(i + '');
    }
  }
}
export class StringLuckyDog extends AbstractLuckyDog {
  constructor(id: string, title: string, type: Type, public string: string[]) {
    super(id, title, type);
    this.count = string.length;
    this.init();
  }
  protected init() {
    this.showModel = [...this.string];
  }
}

export function toLuckyDog(luckyDog: LuckyDog): AbstractLuckyDog {
  const { id, title, type, number, string } = luckyDog;
  switch (luckyDog.type) {
    case 'number': {
      return new NumberLuckyDog(id, title, type, number);
    }
    case 'string': {
      return new StringLuckyDog(id, title, type, string);
    }
  }
}
